package org.aspectsense.middleware.monitor;

import java.lang.annotation.Annotation;
import java.util.EventObject;
import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Logger;
import org.aspectsense.middleware.ComponentContainer;
import org.aspectsense.middleware.Repository;
import org.aspectsense.middleware.controller.AdaptationManager;
import org.aspectsense.middleware.scheduler.RecurringEvent;
import org.aspectsense.middleware.scheduler.Scheduler;

/**
 * For the Middleware Scheduler this class is a RecurringEvent.
 * It is implemented as a Thread and periodically notifies the Scheduler.
 * EventsManager maintains a LinkedList with pending EventObjects which checks
 * constantly and processes until there no other events. Depending on the type
 * of the event in the Queue different methods are called.
 * @author Costas Kakousis
 *
 */
public class EventsManager implements Runnable {

	public static final long INITIAL_WAIT_PERIOD = 0L; // 0 sec
	public static final long THREAD_SLEEP_PERIOD = 500L; // 0.5 sec
	private static final Logger logger = Logger.getLogger(EventsManager.class.getCanonicalName());

	/** The main recurring event used by the system */
	private final RecurringEvent recurringEvent
	= new RecurringEvent(this, INITIAL_WAIT_PERIOD, THREAD_SLEEP_PERIOD);

	private static Queue<EventObject> eventsQueue;

	public EventsManager (){
		eventsQueue = new LinkedList<EventObject>();
	}

	public static void addEvent(EventObject event){
	
		eventsQueue.add(event);
	}

	public void run() {
		EventObject event;
		//While there are still events in queue
	
		if (!eventsQueue.isEmpty()) //TODO is this correct?
		{
			
			//Process events
			event = eventsQueue.poll();
			logger.info("Processing event "+event);
			if(event instanceof OSGiServiceEvent)
			{
				handleOSGiServiceEvent((OSGiServiceEvent) event);
				
			}
		}

	}

	private void handleOSGiServiceEvent(OSGiServiceEvent event) 
	{
		Annotation [] anns;
		ComponentContainer	componentContainer=null;
		
		if(event.getAction().equals(OSGiServiceEvent.Action.REGISTERED))
		{
			
			//Create a new Container for the component that registered this service
			anns = event.getServiceProviderClass().getAnnotations();
			
			if (anns.length>0){
			
				for (Annotation an:anns){
					
					//If an AspectSense class found, create new component container
					if (an.annotationType().getName().compareTo("org.aspectsense.middleware.annotations.AspectSense")==0){
						componentContainer = new ComponentContainer(event.getServiceProviderClass(), event.getBundleName());
						break;
					}
				}
			}
			if (componentContainer!=null)
			{	
				
				Repository.update_Registered(componentContainer);
				Repository.updateTree();
				AdaptationManager.notify(AdaptationManager.EVENT_TYPE.SERVICE_REG, Repository.getProvider(event.getServiceProviderClass().getCanonicalName()));
			}
			
		}
		else if (event.getAction().equals(OSGiServiceEvent.Action.UNREGISTERED))
		{
			Repository.update_Unregistered(event.getServiceProviderClass());
			Repository.updateTree();
			AdaptationManager.notify(AdaptationManager.EVENT_TYPE.SERVICE_UNREG, Repository.getProvider(event.getServiceProviderClass().getCanonicalName()));
		}

	}

	public void activate()
	{
		// schedule event
		Scheduler.getInstance().scheduleEvent(recurringEvent);
		Thread t = new Thread(this);
		t.start();
	}

	public void deactivate()
	{
		// unschedule event
		Scheduler.getInstance().removeRecurringEvent(recurringEvent);
	}

}
